package logger

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

// Property 定义日志属性
type Property struct {
	Name        string      // 属性名称
	Value       interface{} // 属性值
	Format      string      // 格式化字符串
	Alignment   int         // 对齐宽度（正数右对齐，负数左对齐）
	Destructure bool        // 是否需要解构（用于对象）
}

// PropertyType 支持的属性类型,包括:
// - Level: 日志级别
// - Timestamp: 时间戳
// - Message: 日志消息
// - Caller: 调用者信息
// - Pid: 进程ID
// - Goroutine: 协程ID
// - Newline: 换行符
type PropertyType int

const (
	PropTypeUnknown PropertyType = iota
	PropTypeLevel
	PropTypeTimestamp
	PropTypeMessage
	PropTypeCaller
	PropTypePid
	PropTypeGoroutine
	PropTypeNewline
)

// String 实现 Stringer 接口
func (p PropertyType) String() string {
	switch p {
	case PropTypeLevel:
		return "Level"
	case PropTypeTimestamp:
		return "Timestamp"
	case PropTypeMessage:
		return "Message"
	case PropTypeCaller:
		return "Caller"
	case PropTypePid:
		return "Pid"
	case PropTypeGoroutine:
		return "Goroutine"
	case PropTypeNewline:
		return "Newline"
	default:
		return "Unknown"
	}
}

// 添加时间格式常量
const (
	// 预定义的时间格式
	TimeFormatDefault = "2006-01-02 15:04:05"
	TimeFormatDate    = "2006-01-02"
	TimeFormatTime    = "15:04:05"
	TimeFormatYear    = "2006"
	TimeFormatMonth   = "01"
	TimeFormatDay     = "02"
)

// 时间格式映射
var timeFormatMap = map[string]string{
	// 年
	"yyyy": "2006",
	"yy":   "06",
	// 月
	"MM":   "01",
	"M":    "1",
	"MMMM": "January", // 完整月份名
	"MMM":  "Jan",     // 缩写月份名
	// 日
	"dd": "02",
	"d":  "2",
	// 周
	"ww": "02", // 两位周数
	"w":  "2",  // 单位周数
	// 时
	"HH": "15", // 24小时制
	"H":  "15",
	"hh": "03", // 12小时制
	"h":  "3",
	// 分
	"mm": "04",
	"m":  "4",
	// 秒
	"ss": "05",
	"s":  "5",
	// 毫秒
	"SSS": "000",
	"SS":  "00",
	"S":   "0",
	// 时区
	"Z":  "MST",   // 时区缩写
	"ZZ": "-0700", // 时区偏移
}

// TemplateParser 模板解析器
type TemplateParser struct {
	template   string              // 模板字符串
	properties map[string]Property // 保存属性
	timeFormat string              // 时间格式
	propTypes  []PropertyType      // 保存属性类型的顺序
	names      []string            // 保存属性名称的顺序
	formats    []string            // 保存格式化字符串的顺序
}

// parseTemplate 解析模板，提取所需属性
func (p *TemplateParser) parseTemplate() {
	result := p.template
	start := 0

	for {
		startIdx := strings.Index(result[start:], "{")
		if startIdx == -1 {
			break
		}
		startIdx += start

		endIdx := strings.Index(result[startIdx:], "}")
		if endIdx == -1 {
			// 如果找不到结束括号，将剩余文本作为普通文本处理
			break
		}
		endIdx += startIdx

		// 写入前面的文本
		placeholder := result[startIdx+1 : endIdx]
		// 只分割第一个冒号，保留后面的格式字符串
		name := placeholder
		format := ""
		if idx := strings.Index(placeholder, ":"); idx != -1 {
			name = placeholder[:idx]
			format = placeholder[idx+1:]
		}

		// 转换为小写进行比较
		nameLower := strings.ToLower(name)

		// 确定属性类型
		propType := PropTypeUnknown
		switch nameLower {
		case "level":
			propType = PropTypeLevel
		case "timestamp":
			propType = PropTypeTimestamp
		case "message":
			propType = PropTypeMessage
		case "caller":
			propType = PropTypeCaller
		case "pid":
			propType = PropTypePid
		case "goroutine":
			propType = PropTypeGoroutine
		case "newline":
			propType = PropTypeNewline
		}

		// 检查是否是有效的占位符（包含在 { 和 } 之间）
		if strings.Count(result[startIdx:endIdx+1], "{") > 1 {
			// 如果在当前占位符中发现多个 {，说明是不完整的占位符
			// 跳过当前的 { 继续处理
			start = startIdx + 1
			continue
		}

		p.propTypes = append(p.propTypes, propType)
		p.formats = append(p.formats, format)
		p.names = append(p.names, name)

		start = endIdx + 1
	}
}

// NewTemplateParser 创建模板解析器
func NewTemplateParser(template string) *TemplateParser {
	p := &TemplateParser{
		template:   template,
		properties: make(map[string]Property),
		timeFormat: "2006-01-02 15:04:05",
		propTypes:  make([]PropertyType, 0),
		formats:    make([]string, 0),
		names:      make([]string, 0),
	}
	p.parseTemplate()
	return p
}

// WithProperty 添加属性
func (p *TemplateParser) WithProperty(name string, value interface{}) *TemplateParser {
	p.properties[name] = Property{
		Name:  name,
		Value: value,
	}
	return p
}

// WithTimeFormat 设置时间格式
func (p *TemplateParser) WithTimeFormat(format string) *TemplateParser {
	p.timeFormat = format
	return p
}

// Parse 使用预解析的属性列表解析模板
func (p *TemplateParser) Parse() string {
	if len(p.propTypes) == 0 {
		return p.template
	}

	var sb strings.Builder
	sb.Grow(len(p.template) * 2) // 预分配足够的空间
	result := p.template
	start := 0
	propIndex := 0

	for {
		startIdx := strings.Index(result[start:], "{")
		if startIdx == -1 {
			break
		}
		startIdx += start

		endIdx := strings.Index(result[startIdx:], "}")
		if endIdx == -1 {
			// 如果找不到结束括号，将剩余文本作为普通文本处理
			sb.WriteString(result[start:])
			break
		}
		endIdx += startIdx

		// 检查是否是有效的占位符
		if strings.Count(result[startIdx:endIdx+1], "{") > 1 {
			// 如果在当前占位符中发现多个 {，说明是不完整的占位符
			// 将文本直接写入直到第一个 { 之后
			sb.WriteString(result[start : startIdx+1])
			start = startIdx + 1
			continue
		}

		// 写入前面的文本
		sb.WriteString(result[start:startIdx])

		// 根据属性类型获取值
		if propIndex < len(p.propTypes) {
			value := p.formatValue(p.propTypes[propIndex], p.formats[propIndex], p.names[propIndex])
			sb.WriteString(value)
			propIndex++
		}

		start = endIdx + 1
	}

	// 写入剩余文本
	if start < len(result) {
		sb.WriteString(result[start:])
	}

	return sb.String()
}

// formatTime 格式化时间
func (p *TemplateParser) formatTime(t time.Time, format string) string {
	// 特殊格式处理
	switch format {
	case "yyyyww":
		year, week := t.ISOWeek()
		return fmt.Sprintf("%d%02d", year, week)
	case "weekly":
		year, week := t.ISOWeek()
		return fmt.Sprintf("%d-W%02d", year, week)
	}

	// 空格式使用默认格式
	if format == "" {
		return t.Format(p.timeFormat)
	}

	// 解析自定义格式
	var goFormat string
	var lastPos int
	for i := 0; i < len(format); i++ {
		// 查找格式标记
		found := false
		// 按长度降序排序尝试匹配，确保优先匹配最长的格式
		for _, l := range []int{4, 3, 2, 1} {
			if i+l > len(format) {
				continue
			}
			pattern := format[i : i+l]
			if replacement, ok := timeFormatMap[pattern]; ok {
				goFormat += format[lastPos:i] + replacement
				i += l - 1
				lastPos = i + 1
				found = true
				break
			}
		}
		if !found && i == len(format)-1 {
			// 添加剩余的字符
			goFormat += format[lastPos:]
		}
	}

	// 如果没有找到任何格式标记，使用原始格式
	if goFormat == "" {
		return t.Format(format)
	}

	return t.Format(goFormat)
}

// formatValue 根据属性类型格式化值
func (p *TemplateParser) formatValue(propType PropertyType, format string, name string) string {
	if propType == PropTypeNewline {
		return "\n"
	}

	var prop Property
	var ok bool

	if propType != PropTypeUnknown {
		// 对于预定义的属性类型
		prop, ok = p.properties[propType.String()]
	} else {
		// 对于自定义属性，使用当前属性名称
		prop, ok = p.properties[name]
	}

	if !ok {
		// 如果是 level 属性，尝试从格式中解析数字作为日志级别
		if strings.ToLower(name) == "level" && format != "" {
			if level, err := strconv.Atoi(format); err == nil && level >= int(LevelTrace) && level <= int(LevelFatal) {
				return LogLevel(level).String()
			}
		}
		return fmt.Sprintf("[未知属性]")
	}

	// 根据属性类型和格式化字符串处理值
	switch propType {
	case PropTypeTimestamp:
		if t, ok := prop.Value.(time.Time); ok {
			return p.formatTime(t, format)
		}
	case PropTypeLevel:
		if format != "" {
			// 检查是否是纯数字（表示宽度）
			isNumeric := true
			for _, c := range format {
				if c < '0' || c > '9' {
					isNumeric = false
					break
				}
			}
			if isNumeric {
				// 尝试解析数字作为宽度
				if width, err := strconv.Atoi(format); err == nil {
					if level, ok := prop.Value.(LogLevel); ok {
						levelStr := level.Format(width)
						// 如果位数不够,使用空格填充
						if len(levelStr) < width {
							padding := strings.Repeat(" ", width-len(levelStr))
							return levelStr + padding
						}
						return levelStr
					}
				}
				// 如果不是 LogLevel 类型，使用右对齐的字符串格式化
				return fmt.Sprintf(fmt.Sprintf("%%-%ss", format), prop.Value)
			}
			// 其他格式使用原样格式化
			return fmt.Sprintf(fmt.Sprintf("%%%s", format), prop.Value)
		}
	case PropTypeMessage, PropTypeCaller:
		if format != "" {
			return fmt.Sprintf(fmt.Sprintf("%%%s", format), prop.Value)
		}
	case PropTypePid, PropTypeGoroutine:
		if format != "" {
			return fmt.Sprintf(fmt.Sprintf("%%%sd", format), prop.Value)
		}
	default:
		// 处理自定义属性的格式化
		if format != "" {
			// 检查格式化字符串的类型
			switch {
			case strings.Contains(format, "d"):
				// 整数类型格式化
				if v, ok := prop.Value.(int); ok {
					return fmt.Sprintf(fmt.Sprintf("%%%s", format), v)
				}
				// 尝试将浮点数转换为整数
				if v, ok := prop.Value.(float64); ok {
					return fmt.Sprintf(fmt.Sprintf("%%%s", format), int(v))
				}
			case strings.Contains(format, "f"):
				// 浮点数类型格式化
				if v, ok := prop.Value.(float64); ok {
					return fmt.Sprintf(fmt.Sprintf("%%%s", format), v)
				}
			default:
				// 其他类型使用通用格式化
				return fmt.Sprintf(fmt.Sprintf("%%%s", format), prop.Value)
			}
		}
	}

	return fmt.Sprintf("%v", prop.Value)
}

// Reset 重置解析器状态
func (p *TemplateParser) Reset() {
	// 只清空属性映射
	for k := range p.properties {
		delete(p.properties, k)
	}
}
